package com.jugheadzhou.lucene.controller;

import com.jugheadzhou.lucene.model.Content;
import com.jugheadzhou.lucene.service.ContentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author jugheadzhou
 */
@Slf4j
@Controller
@RequestMapping("")
public class LuceneTestController {

    private static final String INDEX_DIR = "D:\\indexDir";

    @Resource
    private ContentService contentService;

    @ResponseBody
    @RequestMapping("/createIndex")
    public String createIndex() throws IOException {
        List<Content> contentList = contentService.selectAll();
        // 创建文档的集合
        List<Document> docs = new ArrayList<>();
        contentList.forEach(content -> {
            // 创建文档对象
            Document document = new Document();
            //StringField会创建索引，但是不会被分词，TextField，即创建索引又会被分词。
            document.add(new StringField("id", content.getId() + "", Field.Store.YES));
            document.add(new TextField("title", content.getTitle(), Field.Store.YES));
            document.add(new TextField("price", content.getPrice(), Field.Store.YES));
            document.add(new TextField("descs", content.getDescs(), Field.Store.YES));
            docs.add(document);
        });
        // 索引目录类,指定索引在硬盘中的位置，我的设置为D盘的indexDir文件夹
        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath(INDEX_DIR));
        // 引入IK分词器

        Analyzer analyzer = new SmartChineseAnalyzer();
        // 索引写出工具的配置对象，这个地方就是最上面报错的问题解决方案
        IndexWriterConfig conf = new IndexWriterConfig(analyzer);
        // 设置打开方式：OpenMode.APPEND 会在索引库的基础上追加新索引。OpenMode.CREATE会先清空原来数据，再提交新的索引
        conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
        // 创建索引的写出工具类。参数：索引的目录和配置信息
        IndexWriter indexWriter = new IndexWriter(directory, conf);
        // 把文档集合交给IndexWriter
        indexWriter.addDocuments(docs);
        // 提交
        indexWriter.commit();
        // 关闭
        indexWriter.close();
        return "success";
    }


    @RequestMapping("/searchText")
    public String searchText(String text, HttpServletRequest request) throws IOException, ParseException {
        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath(INDEX_DIR));
        // 索引读取工具
        IndexReader reader = DirectoryReader.open(directory);
        // 索引搜索工具
        IndexSearcher searcher = new IndexSearcher(reader);
        // 创建查询解析器,两个参数：默认要查询的字段的名称，分词器
        QueryParser parser = new QueryParser("descs", new SmartChineseAnalyzer());
        // 创建查询对象
        Query query = parser.parse(text);
        log.info("debug ==> {}", query);
        // 获取前十条记录
        TopDocs topDocs = searcher.search(query, 10);
        log.info("debug ==> {}", topDocs.totalHits);
        // 获取总条数
        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");
        // 获取得分文档对象（ScoreDoc）数组.SocreDoc中包含：文档的编号、文档的得分
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        List<Content> list = new ArrayList<>();
        for (ScoreDoc scoreDoc : scoreDocs) {
            // 取出文档编号
            int docID = scoreDoc.doc;
            // 根据编号去找文档
            Document doc = searcher.doc(docID);
            Content content = contentService.selectByPrimaryKey(doc.get("id"));
            list.add(content);
        }
        request.setAttribute("list", list);
        return "index";
    }

}
